/*
 * 文件名：MiddlewareManager.java	 
 * 时     间：下午8:57:55
 * 作     者：Administrator       
 * 版     权： 2012-2022 湖南智软网络科技, 公司保留所有权利.
 * 联     系：http://www.073586.com/
 */
package com.local.manager.middleware;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.UnknownHostException;

import com.cz073586.tools.util.Log4jUtil;
import com.cz073586.tools.util.ResourceUtil;
import com.cz073586.tools.util.Tools;
import com.message.entity.TransDataVo;

import common.message.receive.constans.ProtoclConstans;
import common.message.receive.entity.ProtocolDataVo;

/**
 * 类描述: 中间件管理器,主要提供指令下发
 * 
 * @ClassName: MiddlewareManager
 * @author lyf
 * @date 2015年7月13日 下午8:57:55
 */
public class MiddlewareManager
{
	
	private final static Log4jUtil log = Log4jUtil
			.getLog4j(MiddlewareManager.class);
	
	private static MiddlewareManager instance = null;
	
	private String SOCKET_END = "\r\n";
	
	private String middlewareIp;
	private int middlewarePort;
	
	private String encoding = "utf-8";
	private String timeOutCfg;
	private Socket socket;
	
	private MiddlewareManager()
	{
		middlewareIp = ResourceUtil.getValueByKey(
				"config/middleware.properties", "middleware_ip");
		String port = ResourceUtil.getValueByKey(
				"config/middleware.properties", "middleware_port");
		if (!Tools.isEmpty(port))
		{
			this.middlewarePort = Integer.parseInt(port);
		}
		
		encoding = ResourceUtil.getValueByKey("config/middleware.properties",
				"encoding");
		
		timeOutCfg = ResourceUtil.getValueByKey("config/middleware.properties",
				"time_out");
		
	}
	
	/**
	 * 
	 * 方法描述： 初始化与中间件连接
	 * 
	 * @Title: iniSocket
	 * @param
	 * @return void
	 * @user Administrator 2015年7月13日
	 * @throws
	 */
	private void iniSocket(String ip)
	{
		try
		{
			if (!Tools.isEmpty(ip))
			{
				this.socket = new Socket();
				SocketAddress endpoint = new InetSocketAddress(ip, middlewarePort);
				this.socket.connect(endpoint, 2*1000); //一秒连接超时
				this.socket.setReuseAddress(true);// 允许重用Socket
				this.socket.setSoLinger(true, 0);
				
			} else
			{
				// 默认
				//this.socket = new Socket(middlewareIp, middlewarePort);
				
				this.socket = new Socket();
				SocketAddress endpoint = new InetSocketAddress(middlewareIp, middlewarePort);
				this.socket.connect(endpoint, 2*1000); //一秒连接超时
				this.socket.setReuseAddress(true);// 允许重用Socket
				this.socket.setSoLinger(true, 0);
			}
			
		} catch (UnknownHostException e)
		{
			log.error("", e);
		} catch (IOException e)
		{
			log.error("", e);
		}
	}
	
	/**
	 * 
	 * 方法描述： 获取实例
	 * 
	 * @Title: instance
	 * @param @return
	 * @return MiddlewareManager
	 * @user Administrator 2015年7月13日
	 * @throws
	 */
	public static MiddlewareManager instance()
	{
		if (Tools.isEmpty(instance))
		{
			instance = new MiddlewareManager();
		}
		return instance;
	}
	
	/**
	 * @throws IOException
	 * 
	 *             方法描述： 下发指令
	 * 
	 * @Title: sendInstruct
	 * @param @param DeviceNumber 设备编号
	 * @param @param instruct 1.开闸 0.不处理
	 * @param @param host 服务器IP地址
	 * @return void
	 * @user lyf 2015年7月13日
	 * @throws
	 */
	@SuppressWarnings("rawtypes")
	public void sendInstruct(String DeviceNumber, String instruct, String host,
			String middleIP) throws IOException
	{
		try
		{
			
			if (null == this.socket)
			{
				iniSocket(middleIP);
			}
			
			if (socket == null)
			{
				return;
			}
			
			
			/**
			 * 构建请求消息
			 */
			ReqeustEntity request = new ReqeustEntity();
			request.getHeadList().add("Req:Head");
			request.getHeadList().add("Host:" + host);
			request.getHeadList().add("Function-Type:1000");
			request.getHeadList().add("Device-number:" + DeviceNumber);
			request.getHeadList().add("Instruct:" + instruct);
			
			request.getBodyList().add("Req:Body");
			request.getBodyList().add("bye");
			
			OutputStream outStream = this.socket.getOutputStream();
			OutputStreamWriter out = new OutputStreamWriter(outStream);
			
			// 写出请求头
			for (String key : request.getHeadList())
			{
				out.write(key + SOCKET_END);
			}
			
			for (String key : request.getBodyList())
			{
				out.write(key + SOCKET_END);
			}
			
			out.flush();
			
			// 读取返回值
			TransDataVo result = new TransDataVo();
			InputStreamReader read = new InputStreamReader(
					socket.getInputStream(), encoding);
			BufferedReader bRead = new BufferedReader(read);
			
			String readStr;
			ProtocolDataVo responseDataVo = new ProtocolDataVo();
			boolean isHeader = true;
			int timeOut = Integer.parseInt(timeOutCfg);
			int count = 0;
			
			while (!(readStr = bRead.readLine()).equals("bye"))
			{
				// 服务端心跳
				
				if (readStr.equalsIgnoreCase("Server:hello,client."))
				{
					if (count == timeOut)
					{
						result.setErrorCode("20000-30000-50003");
						result.setErrorMsg("连接超时.");
						result.setResult("error");
						break;
					}
					out.write("Client:hello,server."
							+ ProtoclConstans.SOCKET_END);
					out.flush();
					count++;
				}
				
				if (!readStr.equalsIgnoreCase("Body:resp") && isHeader)
				{
					String[] head = readStr.split(":");
					if (head.length > 1)
					{
						responseDataVo.putHeadValue(head[0], head[1]);
					}
					continue;
				}
				
				if (readStr.equalsIgnoreCase("Body:resp"))
				{
					isHeader = false;
					continue;
				}
				
				// 内容
				if (!Tools.isEmpty(readStr))
				{
					break;
				}
			}// end while
			if (responseDataVo.getHeadByKey("State").equals("ok"))
			{
				String insttuct = responseDataVo.getHeadByKey("Instruct");
				if (!Tools.isEmpty(insttuct) && insttuct.equals("1"))
				{
					System.out.println("开闸指令发送成功.");
				}
				
				if (!Tools.isEmpty(insttuct) && insttuct.equals("2"))
				{
					System.out.println("抓拍指令发送成功.");
				}
				
			}
		} catch (Throwable e)
		{
			e.printStackTrace();
		} finally
		{
			if (null != socket)
			{
				
				this.socket.close();
				this.socket = null;
			}
		}
	}
	
	public static void main(String[] agrs) throws IOException
	{
		// no123456:设备编号 1 开闸指令 下发服务器地址
		// MiddlewareManager.instance()
		// .sendInstruct("10002", "2", "192.168.1.100");
		// System.out.println();
	}
}
